﻿/*
 * copyright (c) 2009 hvbird
 *
 * This file is part of tdlib.
 *
 * tdlib is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * tdlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

using System;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Text;

namespace TDLib.Security
{
    /// <summary>
    /// 加密类
    /// </summary>
    public class EncryptTransformer
    {
        private EncryptionAlgorithm algorithmID;
        private byte[] initVec;
        private byte[] encKey;

        /// <summary>
        /// 初始化实例
        /// </summary>
        /// <param name="algId"></param>
        public EncryptTransformer(EncryptionAlgorithm algId)
        {
            algorithmID = algId;
        }

        /// <summary>
        /// 定义加密算法
        /// </summary>
        /// <param name="bytekey">加密的数据</param>
        /// <returns></returns>
        public ICryptoTransform GetCryptoServiceProvider(byte[] bytekey)
        {
            //当数据密钥Key或者初始化向量IV为空的时候，将使用加密对象自动产生的密钥Key或者初始化向量IV 
            switch (algorithmID)
            {
                case EncryptionAlgorithm.Des:
                    {
                        System.Security.Cryptography.DES des = new DESCryptoServiceProvider();
                        des.Mode = CipherMode.CBC;

                        // See if a key was provided 
                        if (null == bytekey)
                        {
                            encKey = des.Key;
                        }
                        else
                        {
                            des.Key = bytekey;
                            encKey = des.Key;
                        }
                        if (null == initVec)
                        {
                            initVec = des.IV;
                        }
                        else
                        {
                            des.IV = initVec;
                        }
                        return des.CreateEncryptor();
                    }
                case EncryptionAlgorithm.TripleDes:
                    {
                        TripleDES des3 = new TripleDESCryptoServiceProvider();
                        des3.Mode = CipherMode.CBC;

                        if (null == bytekey)
                        {
                            encKey = des3.Key;
                        }
                        else
                        {
                            des3.Key = bytekey;
                            encKey = des3.Key;
                        }

                        if (null == initVec)
                        {
                            initVec = des3.IV;
                        }
                        else
                        {
                            des3.IV = initVec;
                        }
                        return des3.CreateEncryptor();
                    }
                case EncryptionAlgorithm.Rc2:
                    {
                        RC2 rc2 = new RC2CryptoServiceProvider();
                        rc2.Mode = CipherMode.CBC;

                        if (null == bytekey)
                        {
                            encKey = rc2.Key;
                        }
                        else
                        {
                            rc2.Key = bytekey;
                            encKey = rc2.Key;
                        }

                        if (null == initVec)
                        {
                            initVec = rc2.IV;
                        }
                        else
                        {
                            rc2.IV = initVec;
                        }
                        return rc2.CreateEncryptor();
                    }
                case EncryptionAlgorithm.Rijndael:
                    {
                        Rijndael rijndael = new RijndaelManaged();
                        rijndael.Mode = CipherMode.CBC;

                        if (null == bytekey)
                        {
                            encKey = rijndael.Key;
                        }
                        else
                        {
                            rijndael.Key = bytekey;
                            encKey = rijndael.Key;
                        }

                        if (null == initVec)
                        {
                            initVec = rijndael.IV;
                        }
                        else
                        {
                            rijndael.IV = initVec;
                        }
                        return rijndael.CreateEncryptor();
                    }
                default:
                    {
                        throw new CryptographicException("Algorithm ID ''" +
                        algorithmID +
                        "'' not supported.");
                    }
            }
        }

        /// <summary>
        /// 获取或设置加密的偏移向量
        /// </summary>
        public byte[] IV
        {
            get { return initVec; }
            set { initVec = value; }
        }

        /// <summary>
        /// 获取或设置加密的密钥
        /// </summary>
        public byte[] Key
        {
            get { return encKey; }
            set { encKey = value; }
        }

    }
}
